package com.bootdo.api.util.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

public class FtpUtil {

	private static Logger logger = Logger.getLogger(FtpUtil.class);

	private static FTPClient ftp;
	
	/**
	 * 获取ftp连接
	 * 
	 * @param f
	 * @return
	 * @throws Exception
	 */
	public static boolean connectFtp(Ftp f) throws Exception {
		ftp = new FTPClient();
		boolean flag = false;
		int reply;
		//如果端口为空，则用默认端口21
		if (f.getPort() == null) {
			ftp.connect(f.getIpAddr(), 21);
		} else {
			ftp.connect(f.getIpAddr(), f.getPort());
		}
		//登入ftp
		ftp.login(f.getUserName(), f.getPwd());
		System.out.println();
		//文件类型为二进制
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
		reply = ftp.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			ftp.disconnect();
			return flag;
		}
		ftp.changeWorkingDirectory(f.getPath());
		flag = true;
		return flag;
	}
	
	/**
	 * 获取ftp连接1
	 * 
	 * @param f
	 * @return
	 * @throws Exception
	 */
	public static FTPClient connectFtp1(Ftp f) throws Exception {
		ftp = new FTPClient();
		int reply;
		//如果端口为空，则用默认端口21
		if (f.getPort() == null) {
			ftp.connect(f.getIpAddr(), 21);
		} else {
			ftp.connect(f.getIpAddr(), f.getPort());
		}
		//登入ftp
		ftp.login(f.getUserName(), f.getPwd());
		System.out.println();
		//文件类型为二进制
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
		reply = ftp.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			ftp.disconnect();
			return ftp;
		}
		ftp.changeWorkingDirectory(f.getPath());
		return ftp;
	}
	
	/**
	 * 关闭ftp连接
	 */
	public static void closeFtp() {
		if (ftp != null && ftp.isConnected()) {
			try {
				ftp.logout();
				ftp.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * ftp上传文件
	 * 
	 * @param f
	 * @throws Exception
	 */
	public static boolean upload(File f) throws Exception {
		//如果文件是个目录，则创建文件夹
		boolean flag = true;
		if (f.isDirectory()) {
			ftp.makeDirectory(f.getName());
			ftp.changeWorkingDirectory(f.getName());
			String[] files = f.list();
			for (String fstr : files) {
				File file1 = new File(f.getPath() + "/" + fstr);
				if (file1.isDirectory()) {
					upload(file1);
					//更改父目录
					ftp.changeToParentDirectory();
				} else {
					File file2 = new File(f.getPath() + "/" + fstr);
					FileInputStream input = new FileInputStream(file2);
					ftp.enterLocalPassiveMode();
					ftp.setControlEncoding("UTF-8");
					ftp.enterLocalPassiveMode();
					String fileName = file2.getName();
					flag = ftp.storeFile(fileName,input);
					input.close();
				}
			}
		} else {
			File file2 = new File(f.getPath());
			System.out.println(f.getPath());
			FileInputStream input = new FileInputStream(file2);
			ftp.setControlEncoding("UTF-8");
			ftp.enterLocalPassiveMode();
			String fileName = file2.getName();
			flag = ftp.storeFile(fileName,input);
			System.out.println(fileName);
			input.close();
		}
		return flag;
	}

	/**
	 * 下载链接配置
	 * 
	 * @param f
	 * @param localBaseDir
	 *            本地目录
	 * @param remoteBaseDir
	 *            远程目录
	 * @throws Exception
	 */
	public static void startDown(Ftp f, String localBaseDir, String remoteBaseDir) throws Exception {
		//判断链接
		if (FtpUtil.connectFtp(f)) {

			try {
				FTPFile[] files = null;
				boolean changedir = ftp.changeWorkingDirectory(remoteBaseDir);
				if (changedir) {
					ftp.enterLocalPassiveMode();
					files = ftp.listFiles();
					for (int i = 0; i < files.length; i++) {
						try {
							downloadFile(files[i], localBaseDir, remoteBaseDir);
						} catch (Exception e) {
							logger.error(e);
							logger.error("<" + files[i].getName() + ">下载失败");
						}
					}
				}
			} catch (Exception e) {
				logger.error(e);
				logger.error("下载过程中出现异常");
			}
		} else {
			logger.error("链接失败！");
		}

	}
	
	
	/**
	 * 下载链接配置(可配置不需要下载的文件和过滤条件)
	 * 
	 * @param f
	 * @param localBaseDir
	 *            本地目录
	 * @param remoteBaseDir
	 *            远程目录
	 * @throws Exception
	 */
	public static List<String> startDown(Ftp f, String localBaseDir, String remoteBaseDir,List<String> fileNames,String startSearchKey,String endSearchKey) throws Exception {
		//本次下载的文件名称
		List<String> list = new ArrayList<String>();
		//判断链接
		if (FtpUtil.connectFtp(f)) {

			try {
				FTPFile[] files = null;
				boolean changedir = ftp.changeWorkingDirectory(remoteBaseDir);
				if (changedir) {
					ftp.enterLocalPassiveMode();
					files = ftp.listFiles();
					//如果文件夹不存在，就创建文件夹
					File dir = new File(localBaseDir);
					if(!dir.exists()){
						dir.mkdirs();
					}
					for (int i = 0; i < files.length; i++) {
						String fileName = files[i].getName();
						boolean startFlag = true;
						boolean endFlag = true;
						if(StringUtils.isNotBlank(startSearchKey)){
							startFlag = fileName.startsWith(startSearchKey);
						}
						if(StringUtils.isNotBlank(endSearchKey)){
							endFlag = fileName.endsWith(endSearchKey);
						}
						if(!fileNames.contains(fileName) && startFlag && endFlag){
							try {
								downloadFile(files[i], localBaseDir, remoteBaseDir);
								list.add(fileName);
							} catch (Exception e) {
								logger.error(e);
								logger.error("<" + files[i].getName() + ">下载失败");
							}
						}
					}
				}
			} catch (Exception e) {
				logger.error(e);
				logger.error("下载过程中出现异常");
			}
		} else {
			logger.error("链接失败！");
		}
		return list;
	}

	/** 
      * 
      * 下载FTP文件 
      * 当你需要下载FTP文件的时候，调用此方法 
      * 根据<b>获取的文件名，本地地址，远程地址</b>进行下载 
      * 
      * @param ftpFile 
      *        文件名
      * @param relativeLocalPath
      *        本地地址 
      * @param relativeRemotePath 
      *        远程地址
      */ 
     public static void downloadFile(FTPFile ftpFile, String relativeLocalPath,String relativeRemotePath) { 
         //判断是否有目录
    	 if (ftpFile.isFile()) {
             if (ftpFile.getName().indexOf("?") == -1) { 
                 OutputStream outputStream = null; 
                 try { 
                     File locaFile= new File(relativeLocalPath+ ftpFile.getName()); 
                     //判断文件是否存在，存在则返回 
                     if(locaFile.exists()){ 
                         return; 
                     }else{ 
                         outputStream = new FileOutputStream(relativeLocalPath+ ftpFile.getName()); 
                         ftp.retrieveFile(ftpFile.getName(), outputStream); 
                         outputStream.flush(); 
                         outputStream.close(); 
                     } 
                 } catch (Exception e) { 
                     logger.error(e);
                 } finally { 
                     try { 
                         if (outputStream != null){ 
                             outputStream.close(); 
                         }
                     } catch (IOException e) { 
                        logger.error("输出文件流异常"); 
                     } 
                 } 
             } 
         } else { 
             String newlocalRelatePath = relativeLocalPath + ftpFile.getName(); 
             String newRemote = new String(relativeRemotePath+ ftpFile.getName().toString()); 
             File fl = new File(newlocalRelatePath); 
             //如果文件不存在则创建文件夹
             if (!fl.exists()) { 
                 fl.mkdirs(); 
             } 
             try { 
                 newlocalRelatePath = newlocalRelatePath + '/'; 
                 newRemote = newRemote + "/"; 
                 String currentWorkDir = ftpFile.getName().toString(); 
                 boolean changedir = ftp.changeWorkingDirectory(currentWorkDir); 
                 if (changedir) { 
                     FTPFile[] files = null; 
                     files = ftp.listFiles(); 
                     for (int i = 0; i < files.length; i++) { 
                         downloadFile(files[i], newlocalRelatePath, newRemote); 
                     } 
                 } 
                 if (changedir){
                     ftp.changeToParentDirectory(); 
                 } 
             } catch (Exception e) { 
                 logger.error(e);
             } 
         } 
     }
     
    
}
